package com.yqb.study.aop.log;

import java.lang.reflect.Method;
import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import com.yqb.study.annotation.log.OperateLogAnt;
import com.yqb.study.aop.AopOrderEnum;
import com.yqb.study.common.bean.BeanFactory;
import com.yqb.study.common.log.LogObjectHolder;
import com.yqb.study.common.log.LogPersistManager;
import com.yqb.study.common.log.LogPersistTaskFactory;
import com.yqb.study.common.warpper.log.BaseLogWarpperMap;
import com.yqb.study.common.warpper.log.LogWarpperMapFactory;
import com.yqb.study.constant.log.LogTypeEnum;
import com.yqb.study.modular.persistence.model.OperateLog;
import com.yqb.study.support.HttpKit;
import com.yqb.study.util.LogContrastUtil;

import ch.qos.logback.core.joran.conditional.ThenOrElseActionBase;

/**
 * 保存日志记录
 */
@Aspect
@Component
public class OperateLogHandler implements Ordered {

	private Logger log = LoggerFactory.getLogger(this.getClass());

	@Pointcut(value = "@annotation(com.yqb.study.annotation.log.OperateLogAnt)")
	public void cutService() {
	}

	@Around("cutService()")
	public Object recordSysLog(ProceedingJoinPoint point) throws Throwable {
		try {
			// 包裹请求参数
			doBeforePoint(point);
		} catch (Exception e) {
			log.error("日志记录出错!", e);
			throw e;
		}		
		
		// 执行业务
		Object result = point.proceed();
		
		// 业务执行成功后,记录正常日志,异常日志在全局异常处理里面记录 
		doAfterPoint(result);

		return result;
	}

	private void doBeforePoint(ProceedingJoinPoint point) throws Exception {
		// --------------------------------------------------------------------------------------------
//		// 如果当前用户未登录，不做日志
//		ShiroUser user = ShiroKit.getUser();
//		if (null == user) {
//			return;
//		}
		// --------------------------------------------------------------------------------------------

		
		// 获取拦截的方法名
		Signature sig = point.getSignature();
		MethodSignature msig = null;
		if (!(sig instanceof MethodSignature)) {
			throw new IllegalArgumentException("该注解只能用于方法");
		}
		msig = (MethodSignature) sig;
		
		// 拦截的实体类
		Object target = point.getTarget();
		// 设置注解的方法
		Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
		String methodName = currentMethod.getName();
		// 获取类名
		String className = point.getTarget().getClass().getName();

		// 获取OperateLogAnt注解标识的几个参数
		OperateLogAnt annotation = currentMethod.getAnnotation(OperateLogAnt.class);
        // 日志的类型
		LogTypeEnum logType = annotation.logTypeEnum();
		// 日志名称
		String logName = annotation.logName();
		// 用于将表单提交字段英文转成中文
		Class logWapperClazz = annotation.logWapperClazz();

		// 如果涉及到修改,比对变化
		String requestWarpperMsg = "";
		// 所有请求参数
		Map<String, String> parameters = HttpKit.getRequestParameters();
		// 创建具体的日志包裹类
		BaseLogWarpperMap logWarpperMap = LogWarpperMapFactory.createLogWarpperMap(logWapperClazz);		
		if (LogTypeEnum.UPDATE_LOG == logType) {
			// 获取修改前的对象
			Object originObj = LogObjectHolder.me().getObject();
			// 比较
			requestWarpperMsg = LogContrastUtil.contrastObj(logWarpperMap, originObj, parameters);
		} else {
			requestWarpperMsg = LogContrastUtil.parseLogField(logWarpperMap, parameters);
		}

		// 保存日志请求参数处理
		LogObjectHolder.me().setOperateLog(BeanFactory.createOperateLog(logType.getNum().toString(), logName, 11111, className, methodName, "成功", HttpKit.getIp(), requestWarpperMsg, null));
	}
	
	private void doAfterPoint(Object result) {
		// 取出日志请求参数处理结果
		OperateLog operateLog = LogObjectHolder.me().getOperateLog();
		operateLog.setResult(result.toString());
		
		// 异步保存日志
		LogPersistManager.me().execute(LogPersistTaskFactory.operateLog(operateLog));		
	}

	@Override
	public int getOrder() {
		return AopOrderEnum.LOG_AOP.getNum();
	}
}